4.2 自制音频播放器
支持本地音频以及流媒体在线播放。
UI 架子
from tkinter import *
import tkinter.ttk as ttk
from tkinter.font import Font
from PIL import Image, ImageTk
from resource import control_icon, bottom_icon
from seekbar import Seekbar
import Pmw
class AudioView(Tk):
def __init__(self):
super().__init__()
self._init_data_()
self._set_window_()
self._create_menu_bar()
self._create_top_view()
self._create_control_panel()
self._create_list_box()
self._create_bottom_view()
if "__main__" == __name__:
app = AudioView()
app.mainloop()
Tkinter 的细节问题
Tkinter 的各小控件在实际使用中,都会存在一些细节问题,这些细节问题不是在初识小控件的时候能弄明白的,需要有一定的实战经验,并结合具体的项目才能体会出来。
设置窗体透明度
这部分描述,在
tkinter
文档中并未描述,我们需要查看tcl/Tk
的 相关文档 ,关于窗口feature
的设置,推荐阅览本人另一篇博客 传送门,利用这点能实现桌面悬浮控件,可用于歌词展现self.wm_attributes("-alpha", 0.9)
LabelFrame
的扩展用法menu_frame = Frame(bg="black") frame = LabelFrame(self, labelwidget=menu_frame, bg="black", borderwidth=2, padx=10, pady=8, relief="sunken")
Listbox
的深入学习给
Listbox
添加右键选中菜单self.list_box = Listbox(frame, bg="black", yscrollcommand=y_bar.set, fg="white", xscrollcommand=x_bar.set, border=0, highlightthickness=0, selectforeground="#F0F126", selectbackground="black", activestyle="none", font=("微软雅黑", -18), height=8) self.list_box.bind('<Double-Button-1>', self.list_selected) self.list_box.bind("<Button-3>", self.show_context_menu) # 设置选中 if self.list_box.size() == 1: self.list_box.selection_set(0) def show_context_menu(self, event): # 清除鼠标右键选中色 for i in range(self.list_box.size()): self.list_box.itemconfig(i, background="black") # 获取当前鼠标右键选中的索引 index = self.list_box.nearest(event.y) # 选中后改变背景色 self.list_box.itemconfig(index, background="gray") self.context_menu.entryconfigure(0, command=lambda: self.remove_at(index)) self.context_menu.tk_popup(event.x_root, event.y_root)
Canvas
与自定义控件该项目中,我们主要自定义的是一个音频进度条控件
Seekbar
。主要使用Canvas的coords
函数来移动对象,关于Canvas支持的一些功能,列举如下create_arc():绘制弧。
create_bitmap():绘制位图。
create_image():绘制图像。
create_line():绘制线段。
create_oval():绘制椭圆。
create_polygon():绘制多边形。
create_rectangle():绘制矩形。
create_text():绘制文本。
create_window():绘制矩形窗口。
在
Seekbar
中,我们监听了鼠标按下和移动事件,关于事件的修饰符,可以查看tcl/Tk
的官方文档,内容比tkinter
要全面很多,相关部分文档
VLC 多媒体框架
它是一款自由、开源的跨平台多媒体播放器及框架,全面支持绝大部分的多媒体格式,以及各类流媒体协议。也就是说,使用它既能播放本地音视频文件,也能在线播放各类流媒体资源。
关于VLC的安装与详细使用,请阅览本人博客 传送门
Tkinter 与异步编程
关于在Tkinter中使用消息队列 + 多线程
实现异步任务方法,我早前已写过详细博客 传送门 看一下博客即可。
当前这个项目,我们将使用另一种更加简洁高效的方式实现异步任务——线程池
from concurrent.futures import ThreadPoolExecutor
class RequestTask():
task = None
def __init__(self):
self.executor = ThreadPoolExecutor(max_workers=1)
# 用submit添加耗时任务,该函数会立即返回,不会阻塞
def request(self, url, count):
self.task = self.executor.submit(get_music_list, url, count)
# 检查异步任务是否执行完成
def check_task(self):
return self.task.done()
# 获取异步任务执行结果
def get_result(self):
return self.task.result()
遗留问题
- 该视频播放器为简单实现,后续大家可以添加收藏、本地歌单、网易云音乐本地缓存、在线歌单筛选、桌面歌词等等功能
- 对于
VCL
库的所有调用均在主线程中进行,当VCL
库的API
耗时或阻塞时,会造成界面无响应。要改善该问题,可以考虑将音频播放移入后台线程中运行,而不阻塞前台的GUI - 本地音频文件格式筛选,不要将非音频文件导入
- 响应快捷键,包括控制栏上的播放、暂停、快进等
- 界面美化
完整项目源码 传送门